<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!--
Copyright (c) 2007 Brian Dillard and Brad Neuberg:
Brian Dillard | Project Lead | bdillard@pathf.com | http://blogs.pathf.com/agileajax/
Brad Neuberg | Original Project Creator | http://codinginparadise.org

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-->

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	
<title>Really Simple History: Test Page</title>

<script type="text/javascript" src="json2007.js"></script>
<script type="text/javascript" src="rsh.compressed.js"></script>

<script type="text/javascript">
/*instantiate our history object*/
window.dhtmlHistory.create({
	debugMode: true//set this to false, or just don't pass in an options bundle, to see real-world, non-debug conditions 
});
</script>

<script type="text/javascript">

window.onload = function() {
	//initialize our DHTML history
	dhtmlHistory.initialize();
	log("<b>dhtmlHistory initialized</b>");

	//subscribe to DHTML history change events
	dhtmlHistory.addListener(historyChange);
	log("<b>dhtmlHistory listener created</b>");
};

/*basic DHTML logging for our test page*/
function log(msg) {
	var logNode = document.getElementById("logWin");
	var content = "<p>" + msg + "</p>" + logNode.innerHTML;
	logNode.innerHTML = content;
}
function clearLog(msg) {
	var logNode = document.getElementById("logWin");
	logNode.innerHTML = "";
}
function printBrowserInfo() {
	//Print out browser details for QA
	log("<b>Begin browser dump</b>");
	log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigator.appCodeName: " + navigator.appCodeName);
	log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigator.appName: " + navigator.appCodeName);
	log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigator.appVersion: " + navigator.appVersion);
	log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigator.userAgent: " + navigator.userAgent);
	log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigator.platform: " + navigator.platform);
	log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;navigator.vendor: " + navigator.vendor);
	log("<b>End browser dump</b>");
}

/*set up test cases for dhtmlHistory*/
var rawIndex = 0;
var rawMaterial = [
	["one", "Hello World Data"],
	["two", 33],
	["three", true],
	["four", true],
	["5","let's try a digit"],
	["four","value of 'four' has now been reset"],
	["complexObject",{
		value1: "This is value1",
		value2: "This is value2",
		value3: ["This is array[0]","This is array[1]"]
	}],
	["seven",[0,1,"three","five",9]],
	["8","more data"]
	["complexObject",{
		new1: "all-new",
		new2: "all-different",
		new3: ["it's","the","uncanny","complexObject"]
	}],
];

function callHSTest(hash,val) {
	historyStorage.put(hash,val);
	log("Setting key <b>" + hash + "</b> to value <b>" + val + "</b>.");
}

/*set up test cases for historyStorage*/
function testHistoryStorage() {
	log("<b>Begin historyStorage test suite.</b>");
	
	callHSTest("pageLoaded", true);
	callHSTest("removeMe1", "remove me 1");
	callHSTest("message", "Hello World");
	callHSTest("removeMe2", "remove me 2");
	callHSTest("field", "Watson, come quick!");
	callHSTest("removeMe3", "remove me 3");
	callHSTest("complexObject",{
		value1: "value1",
		value2: "value2",
		value3: ["array[0]","array[1]"]
	});

	historyStorage.remove("removeMe1");
	historyStorage.remove("removeMe2");
	historyStorage.remove("removeMe3");
	log("Removing several keys to test history removal operation.");

	if (
		historyStorage.hasKey("removeMe1")
		|| historyStorage.hasKey("removeMe2")
		|| historyStorage.hasKey("removeMe3")
	){
		log("<b>Removal failed. There must be a bug in the framework.</b>");
	}
	else {
		log("Removal succeeded.");
	}

	var pageLoaded = historyStorage.get("pageLoaded");
	log("Retrieving key <b>pageLoaded</b>. Value = <b>" + pageLoaded + "</b>.");

	log("Testing hasKey method on key <b>message</b>. Method hasKey returns <b>" + historyStorage.hasKey("message") + "</b>.");
	var message = historyStorage.get("message");
	log("Retrieving key <b>message</b>. Value = <b>" + message + "</b>.");

	log("Testing hasKey method on key <b>field</b>. Method hasKey returns <b>" + historyStorage.hasKey("field") + "</b>.");
	var field = historyStorage.get("field");
	log("Retrieving key <b>field</b>. Value = <b>" + field + "</b>.");

	log("Testing hasKey method on key <b>complexObject</b>. Method hasKey returns <b>" + historyStorage.hasKey("complexObject") + "</b>.");
	var complexObject = historyStorage.get("complexObject");
	log("Retrieving key <b>complexObject</b>. Next several lines will look at its members.");
	log("complexObject.value1 = <b>" + complexObject.value1 + "</b>.");
	log("complexObject.value2 = <b>" + complexObject.value2 + "</b>.");
	log("complexObject.value3[0] = <b>" + complexObject.value3[0] + "</b>.");
	log("complexObject.value3[1] = <b>" + complexObject.value3[1] + "</b>.");
    
	log("Testing method hasKey on a non-existent key called <b>bad</b>. Method hasKey returns <b>" + historyStorage.hasKey("bad") + "</b>.");
	var bad = historyStorage.get("bad");
	log("Retrieving non-existent key <b>bad</b>. Value = <b>" + bad + "</b>.");
	if (bad != null) {
		log("<b>The above value should have been null but wasn't. There must be an error in the framework.</b>");
	}
	log("<b>End historyStorage test suite.</b>");
}
function testComplexXML() {
	loadTopSubscriptions();
}	

function historyChange(newLocation, historyData) {
	var historyMsg = (typeof historyData == "object" && historyData != null
		? historyStorage.toJSON(historyData)
		: historyData
	);
	var msg = "<b>A history change has occured:</b> | newLocation=" + newLocation + " | historyData=" + historyMsg + " |";
	log(msg);
};

/* Our event handler to add history change events */
addHistoryEvent = function() {
	if (!rawMaterial[rawIndex]) {
		rawIndex = 0;
	}
	var a = rawMaterial[rawIndex];
	dhtmlHistory.add(a[0],a[1]);
	if (typeof a[1] == "object") {/*stringify this so we can log it better*/
		a[1] = historyStorage.toJSON(a[1]);
	}
	var msg = "<b>A history event has been added:</b> [newLocation=" + a[0] + " | historyData=" + a[1] + "]";
	log(msg);
	rawIndex++;
}

/*basic Ajax wrapper*/
function getXHR() {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		return new ActiveXObject("Microsoft.XMLHTTP");
	}
}

/* Converts pointy brackets into their HTML escape code equivalents so we can print out XML. */
function prettyPrintXml(content) {
	if (content == null) {
		return null;
	}
	content = content.replace(/</g, "&lt;");
	content = content.replace(/>/g, "&gt;<br />");
	return content;
}


function logTopSubscriptions() {
	log(prettyPrintXml(historyStorage.get('mySubscriptions')));
}
/* Gets the top 100 blog subscriptions as an OPML outline. - for a historyStorage test case */
function loadTopSubscriptions() {
	log("Loading top subscriptions...");
	var url = "rshTestPageTop100.opml";
	var request = getXHR();
	var processRequest = function() {
		if (request.readyState == 4) {
			if (request.status == 200) {
				historyStorage.put("mySubscriptions", request.responseText);
				log("Top subscriptions loaded");
				log('Put complex XML document into key "mySubscriptions"');
				log('<a href="javascript:logTopSubscriptions();">Click here to log the entire XML document.</a> Warning: it\'s huge.');
				topLoaded = true;
			}
			else {
				var message = "There was a problem retrieving the subscription list: " + request.statusText
				log(message);
			}
		}
	};
	request.onreadystatechange = processRequest;
	request.open("GET", url, true);
	request.send("");
}
function toggleInstructions() {
	var node = document.getElementById('instructions');
	var state = node.style.display || "none";
	node.style.display = (state == "none" ? "block" : "none");
}
function viewObjectState() {
	log("<b>Dumping dhtmlHistory object state</b>");
	for (var key in dhtmlHistory) {
		var val = dhtmlHistory[key];
		if (typeof val !== 'function' && (typeof val !== 'object' || val === null)) {
			log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>" + key + "</b>: " + dhtmlHistory[key]);
		}
	}
	log("<b>Done dumping dhtmlHistory object state</b>");
	log("<b>Dumping historyStorage object state</b>");
	for (var key in historyStorage) {
		var val = historyStorage[key];
		if (typeof val != 'function' && typeof val != 'object') {
			log("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>" + key + "</b>: " + historyStorage[key]);
		}
	}
	log("<b>Done dumping historyStorage object state</b>");
}
</script>

<style type="text/css">
	body {
		margin: 0;
		padding: 8px;
		font: .9em "Trebuchet MS", verdana, arial, helvetica, sans-serif;		
	}
	p,h1,h2,div {
		margin: 0 0 8px 0;
		padding: 0;
	}
	h1 {
		font-size: 1.2em;
	}
	h2 {
		font-size: 1.1em;
	}
	hr {
		color: #fff;
		margin: 3px 0;
		border: 0;
		border-top: 1px solid black;
	}
	.log{
		width: 790px;
		padding: 5px;
		height: 400px;
		border: 1px solid black;
		overflow: auto;
		color: #333;
		font-size: .8em;
	}
	.log p{
		margin: 0 0 5px 0;
	}
	.log div{
		margin: 5px 0;
		padding: 5px 0;
		border-top: 1px solid black;
		border-bottom: 1px solid black;
	}
	#instructions{
		border: 3px dashed #930;
		padding: 10px;
		width: 780px;
		background-color: #ccc;
		display: none;
	}
</style>

</head>

<body>
	
<p>
	| <a href="javascript:toggleInstructions();">toggle instructions</a>
	| <a href="javascript:printBrowserInfo();">log browser</a>
	| <a href="javascript:viewObjectState();">log object state</a>	
	| <a href="javascript:clearLog();">clear log</a>
|</p>
<p>	
	| <a href="javascript:addHistoryEvent();">add history</a>
	| <a href="http://code.google.com/p/reallysimplehistory/">go off-site</a>
	| <a href="javascript:testHistoryStorage();">test storage</a>
	| <a href="javascript:testComplexXML();">test XML</a>
|</p>

<h1>Really Simple History Test Page</h1>

<div id="instructions">
	<h2>Really Simple History Testing Instructions</h2>
	
	<p>This utility is designed to test the functionality of Really Simple History's historyStorage and dhtmlHistory objects.</p>
	
	<p>Use the links above to:</p>
	
	<ul>
		<li>Add history events one at a time and see them logged.</li>
		<li>Navigate off-site so you can then return with the back button and confirm your history was retained.</li>
		<li>Run a large suite of historyStorage tests and view the results.</li>
		<li>Run a separate historyStorage test to see how it handles serialization of complex XML data loaded via XHR.</li>
		<li>Log your browser stats so you can report browser-specific bugs over in the <a href="http://code.google.com/p/reallysimplehistory/issues/list">Google Code issue tracker</a>.</li>
	</ul>
	
	<p><b>CAVEAT:</b>Don't try to run this test page, or RSH in general, from your desktop. Always view it from a webserver (even localhost); otherwise its behavior will be extremely flaky, especially in IE.</p>
	
	<p><b>QUESTIONS?</b> Email bdillard(at)pathf(dot)com, visit the <a href="http://groups.google.com/group/reallysimplehistory">Google Group</a> or log something in the <a href="http://code.google.com/p/reallysimplehistory/issues/list">issue tracker</a>.</p>
	
	<a href="javascript:toggleInstructions();">hide these instructions</a>
</div>

<h2>Log Window</h2>
<div class="log" id="logWin"></div>

</body>
</html>

